昨天看到FetchData.razor
的程式太長了,截圖都要兩次,為求方便,我們把@code
的部分擷取出來另成一個檔案。
Blazor提供了兩個方法:partial class
跟ComponentBase
,同樣兩者各有優缺點,筆者偏好ComponentBase
,端看個人使用習慣。
先來看partial class
,我們打開FetchData.razor
,把前面提到的@using BlazorServer.Data
移到_Imports.razor
,再建立一個class
叫做FetchData.razor.cs
,在public
跟class
中間加上partial
修飾詞,接著把FetchData.razor
的@code區塊剪下貼到FetchData.razor.cs
後稍作修改,可以看出跟舊的C#程式沒什麼差別。我們按下F5,一樣看到10筆天氣資料。
接著來看ComponentBase
,先把partial class
裡面的程式複製下來,接著建立一個新class
取名為FetchDataBase.cs
,將剛剛的程式貼上後稍做修改,再刪除FetchData.razor.cs
這個partial class,因為兩種模式不能並存。可以看到除了繼承ComponentBase
跟加上[Inject]
外,幾乎沒有差別,這裡的[Inject]
相當於在FetchData.razor.cs
使用@inject WeatherForecastService ForecastService
,我們按下F5啟動偵錯模式,在20行左邊按一下設定中斷點,可以看到一樣取得了天氣資料。
接著開始做自己的Component吧!先將不必要的Component刪除,Startup.cs
跟_Import.razor
裡面跟天氣有關的using
及註冊同樣刪除,如果忘記這兩個檔案在哪裡,可以在刪除Component後將滑鼠移到專案BlazorServer點右鍵,選取重建專案,Visual Studio就會告訴你哪裡出錯了。
之前說過要完成讓使用者寫日誌的網站,所以需要最基本的輸入框,而日誌的單位就以一篇計算。首先建立Models資料夾,建立PostModel
類別,裡面很簡單只有3個屬性,接著在Pages資料夾建立Post.razor
跟PostBase.razor.cs
,最後將NavMenu.razor
的連結留下一個,href
屬性的值改為Post
。
PostModel
是用來承接資料的容器,目前沒有Service,所以在PostBase.razor.cs
放一筆假資料,這邊可以看到一個方法OnInitializedAsync()
,代表當這個Component生命週期伊始,裡面的事情就會先做,其他還有OnAfterRenderAsync
、OnParametersSetAsync
等等,只要先輸入override
再按一下空白鍵,就可以看到這些方法,且也有同步跟非同步兩種模式,這些方法有機會再說明。
而Post.razor
用了EditForm
這個Component,編譯過後相當於html的form元素,裡面還有3個input元素,Blazor也有提供相對應的Input Component,可以從官方文件看到分別編譯後的html元素。
這時候打開網頁來看,可以看到上面出現了我們定義在PostBase.razor.cs
的值,但這是怎麼連結起來的呢?原因就是EditForm的Model屬性及3個<Input>
Component的屬性@bind-Value
,這裡在告訴Blazor:我的Model跟裡面的值要跟這個EditForm綁在一起,如果這裡有跟後端程式連結,網頁上輸入的內容經過事件觸發後,就會送到後端處理。
不過<Input>
預設的CSS樣式不太好看,我們先套用基本的boostrap樣式;因為Id通常不會讓使用者輸入,所以這邊先註解,然後再加入表格驗證機制,畢竟不能讓使用者隨便輸入就送出表格,但如果不想自己寫一堆驗證機制呢?可以試試看Blazor的DataAnnotationsValidator
及ValidationSummary
兩個Component。
我們先在PostModel
的Title
跟Content
加上兩個Attribute
,Required
代表必填,MaxLength
及MinLength
則是限制最大及最小字數,還可以自訂錯誤訊息。接著在EditForm
裡面加上那兩個Component DataAnnotationsValidator
及ValidationSummary
,第一個是驗證個別Input
,第二個則是將錯誤訊息顯示在表格上方。
但如果不喜歡驗證機制預設的CSS樣式呢?Blazor也提供客製化的方法。先建立一個class
名為CustomFieldClassProvider
且繼承FieldCssClassProvider
,覆寫方法GetFieldCssClass
,裡面的內容待會再說。
接著在PostBase.razor.cs
加入一個類別為EditContext
的屬性editContext
,初始化產生物件editContext
,將原本的Post物件丟進去建構子,然後呼叫editContext
的方法SetFieldCssClassProvider
,在建構子產生新CustomFieldClassProvider
物件。
最後最重要的一步,在Post.razor
將EditForm
的Model參數移除,改為EditContext
參數,裡面的值就是剛剛的editContext
物件。
這時候再送出表格一次,可以看到textarea的紅色外框消失了,字體也變成text-danger
的紅色,而正確的欄位則是變成text-primary
的藍色。我們再回頭看CustomFieldClassProvider
,原來editContext
指的就是EditForm
的內容,fieldIdentifier
則是個別Input
,如果editContext
呼叫的方法GetValidationMessages
有在fieldIdentifier
取得任何訊息,代表這是錯誤的欄位,沒有則是正確欄位,這就是Blazor幫我們客製化Form的作法。
Ref: Split HTML And C# Code In Blazor Using Either Partial Class Or ComponentBase Class
https://www.learmoreseekmore.com/2020/06/blazor-paratial-class-or-componentbase-class.html
Ref: ASP.NET Core Blazor forms and validation
https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#binding-a-form
Ref: Custom validation CSS class attributes
https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#custom-validation-css-class-attributes-1